#include "rel.h"

/**
 * Determines the host machine's endianness.
 *
 * @return 1 if Little Endian, 0 if Big Endian
 */

int checkEndian () {

  void * p;
  unsigned short * shortP;
  
  unsigned char buffer[2];
  p = (void * ) buffer;
  shortP = (unsigned short * ) p;
  
  * shortP = 0x01;  
  
  if (buffer[0] == 0x00){
    if (debug) {
      printf("\nTesting Endianness: Big Endian\n");
    }
    return false;
  }
  
  else {
    if (debug) {
      printf("\nTesting Endianness: Little Endian\n");
    }
    return true;
  }

}

 /**
  * Given a long long number reverse the order of the bytes
  * if the machine is Little Endian.  Otherwise do nothing and
  * return the number.
  *
  * @param input - host value to be converted to network order
  */
 
  unsigned long long htonll(unsigned long long input) {
    return ntohll(input); 
  }
 
 /**
  * Given a long long number reverse the order of the bytes
  * if the machine is Little Endian.  Otherwise do nothing and
  * return the number.
  *
  * @param input - network value to be converted to host order
  */
  unsigned long long ntohll (unsigned long long input) {
    if (checkEndian()){
      unsigned long long result = 0;
      unsigned long long mask = 0xFF;
      
      if (debug){
        printf("\nTesting host to network conversion functions:\n");
        // Print INPUT      
        void * p;
        unsigned char * buffer;
        p = (void *) &input;
        buffer = (unsigned char * ) p;
        int j;
        for (j = 7; j >= 0; j--) {
          printf("%x ", buffer[j]);
        }    
        printf("\n");
      }
      
      // Input will be reversed
      // Need to reverse all 8 bytes
      int i;
      for ( i = 0; i < 8 ; i ++){
         
        if (i < 4) {
          result = result | ((input & ( mask << (i * 8) )) << (8 * (7 - 2 * i) ));
        }
        else {
          result = result | ((input & ( mask << (i * 8) )) >> (8 * ( 2 * (i - 4) + 1) ));
        }
      }      
      // Print resulting value 
        if (debug) {
          void * p;
          unsigned char * bufferResult;
          p = (void *) &result;
          bufferResult = (unsigned char * ) p;
          int j;
          
          for (j = 7; j >= 0; j--) {
            printf("%x ", bufferResult[j]);
          }
        printf("\n");
      }   
      return result;
    }
    
    // If Big Endian, we can just return value without swapping bytes
    else {
      return input;
    }
  }

 